package PolygonHelper

import "math"

const (
	OddEvenFill = iota
	WindingFill
)

type Point struct {
	X float64
	Y float64
}

/**
多边形是否包含点
*/
type PolygonContains struct {
	points []Point
}

func (this *PolygonContains) Append(p Point) {
	this.points = append(this.points, p)
}

func (this *PolygonContains) Clear() {
	this.points = this.points[0:0]
}

func (this *PolygonContains) ContainsPoint(pt Point) bool {
	return this.containsPointFil(pt, WindingFill)
}

func (this *PolygonContains) containsPointFil(pt Point, fillrule int) bool {
	if len(this.points) == 0 {
		return false
	}
	winding_number := 0
	last_pt := this.points[0]
	last_start := this.points[0]
	for _, e := range this.points {
		this.polygonIsectLine(last_pt, e, pt, &winding_number)
		last_pt = e
	}
	if last_pt != last_start {
		this.polygonIsectLine(last_pt, last_start, pt, &winding_number)
	}
	if fillrule == OddEvenFill {
		return (winding_number != 0)
	}
	return (winding_number%2 != 0)
}

func (this *PolygonContains) fuzzyCompare(p1, p2 float64) bool {
	return (math.Abs(float64(p1-p2)) <= 0.00001*math.Min(math.Abs(float64(p1)), math.Abs(float64(p2))))
}

func (this *PolygonContains) polygonIsectLine(p1, p2, pos Point, winding *int) {
	x1, y1, x2, y2, y := p1.X, p1.Y, p2.X, p2.Y, pos.Y
	dir := 1
	if this.fuzzyCompare(y1, y2) {
		return
	} else if y2 < y1 {
		x1, x2 = x2, x1
		y1, y2 = y2, y1
		dir = -1
	}
	if y >= y1 && y < y2 {
		x := x1 + ((x2-x1)/(y2-y1))*(y-y1)
		if x <= pos.X {
			(*winding) += dir
		}
	}
}
